﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Implementation;
using Interfaces;

/**
 * 
 * \file CarteXaml.xaml.cs
 * \brief Carte Xaml
 * \author Baptiste Villiot - Jonathan Langlais
 * \version 1.0
 * 
 */

namespace CivilisationWPF
{
    /**
   * 
   * \class CarteXaml
   * \brief Affiche la carte et tous les elements qu'elle peut contenir
   * 
    */
    public partial class CarteXaml : Canvas
    {
        /**
         * !< le monteur de partie
         */
        private MonteurPartie monteur;

        /**
         * !< la taille de la carte
         */
        private int taille;

        /**
         * !< indique si la ville a ete construite
         */
        private bool villeConstruite;

        /**
         * !< la ville selectionnee
         */
        private Ville villeCourante;

        /**
         * !< la fenetre ou est affichee la carte
         */
        MainWindow _main;

        /**
         * \fn CarteXaml()
         * \brief Constructeur de CarteXaml
         */
        public CarteXaml()
        {
            InitializeComponent();
            monteur = new MonteurPartieImpl();
            //infoCase.Children.Add(new InfoCase());
        }

        /**
         * \fn CarteXaml(MonteurPartie mont,MainWindow main)
         * \brief Constructeur de CarteXaml
         * \param[in] mont le monteur
         * \param[in] main la fenetre
         */
        public CarteXaml(MonteurPartie mont,MainWindow main)
        {
            _main = main;
            InitializeComponent();
            monteur = mont;
            joueurCourant.Tag = monteur.getJoueurCourant();
            infoVille.Children.Clear();
        }

        /**
         * \fn CarteXaml(MonteurPartie mont, MonteurPartieImpl.strategie str,MainWindow main)
         * \brief Constructeur de CarteXaml
         * \param[in] mont le monteur
         * \param[in] str la strategie
         * \param[in] main la fenetre
         */
        public CarteXaml(MonteurPartie mont, MonteurPartieImpl.strategie str,MainWindow main)
        {
            InitializeComponent();
            _main = main;
            monteur = mont;
            //strategie = str;
            joueurCourant.Tag = monteur.getJoueurCourant();
            infoVille.Children.Clear();
            Carte c = monteur.creerCarte(str);
            c.creer();
            faireCarte(c);
        }

        /**
         * \fn faireCarte(Carte c)
         * \brief creer la grille pour afficher la carte
         * \param[in] c la carte
         */
        public void faireCarte(Carte c)
        {
            taille = c.getTaille();
            for (int i = 0; i < taille; i++)
            {
                carteGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(30, GridUnitType.Pixel) });
            }
            for (int j = 0; j < taille; j++)
            {
                carteGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(30, GridUnitType.Pixel) });
                for (int i = 0; i < taille; i++)
                {
                    createImage(c.getCaseDic().Where(p => p.Key.Item1 == j && p.Key.Item2 == i).First().Value, j, i);
                }
            }
            updateUnit();
            mettreAJour();
            initVille();
        }

        /**
         * \fn createImage(Case c, int j, int i)
         * \brief creer les images 
         * \param[in] c la carte
         * \param[in] j l'ordonnee de la case
         * \param[in] i l'abscisse de la case
         */
        public void createImage(Case c, int j, int i)
        {
            Grid rect = new Grid();
            Grid deco = new Grid();
            rect.Tag = c;
            rect.MouseLeftButtonDown += new MouseButtonEventHandler(rectangle_MouseLeftButtonDown);
            rect.MouseRightButtonDown += rectangle_MouseRightButtonDown;
            Grid.SetColumn(rect, j);
            Grid.SetRow(rect, i);
            Grid.SetColumn(deco, j);
            Grid.SetRow(deco, i);

            ImageBrush bi = new ImageBrush();
            ImageBrush bi2 = new ImageBrush();

            if (c is CaseDesertImpl)
            {
                bi.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.desert.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            }
            else if (c is CaseMontagneImpl)
            {
                bi.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.montagne.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            }
            else if (c is CasePlaineImpl)
            {
                bi.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.plaine.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            }
            else if (c is DecorateurCaseFer)
            {
                DecorateurCaseFer dc = (DecorateurCaseFer)c;

                if (dc.caseBase is CaseDesertImpl)
                {
                    bi.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.desert.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                    bi2.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.fer.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                }
                else if (dc.caseBase is CaseMontagneImpl)
                {
                    bi.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.montagne.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                    bi2.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.fer.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                }
                else if (dc.caseBase is CasePlaineImpl)
                {
                    bi.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.plaine.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                    bi2.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.fer.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                }
                else
                {
                    rect.Background = Brushes.Red;
                }
            }
            else if (c is DecorateurCaseFruit)
            {
                DecorateurCaseFruit dc = (DecorateurCaseFruit)c;
                if (dc.caseBase is CaseDesertImpl)
                {
                    bi.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.desert.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                    bi2.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.fruit.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                }
                else if (dc.caseBase is CaseMontagneImpl)
                {
                    bi.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.montagne.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                    bi2.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.fruit.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                }
                else if (dc.caseBase is CasePlaineImpl)
                {
                    bi.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.plaine.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                    bi2.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.fruit.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                }
                else
                {
                    rect.Background = Brushes.Red;
                }
            }
            else
            {
                rect.Background = Brushes.Red;
            }
            rect.Background = bi;
            deco.Background = bi2;
            rect.Children.Add(deco);
            carteGrid.Children.Add(rect);
        }

        /**
         * \fn mettreAJour()
         * \brief met a jour la partie
         */
        void mettreAJour()
        {
            SolidColorBrush couleur = new SolidColorBrush();
            switch (MonteurPartieImpl.joueurCourant.getCouleur())
            {
                case 1:
                    couleur = Brushes.Red;
                    break;
                case 2:
                    couleur = Brushes.Blue;
                    break;
                case 3:
                    couleur = Brushes.Green;
                    break;
                case 4:
                    couleur = Brushes.Yellow;
                    break;
            }
            couleurInfoCase.Background = couleur;
            couleurListeUnite.Background = couleur;
            Tuple<int, int> t = new Tuple<int, int>(Grid.GetColumn(selectionRectangle), Grid.GetRow(selectionRectangle));

            afficherInfoUnite(t);
            infoVille.Children.Clear();
            if (MonteurPartieImpl.joueurCourant.ville != null)
            {
                if (MonteurPartieImpl.joueurCourant.ville.Count((vi => vi.position.Item1 == t.Item1 & vi.position.Item2 == t.Item2)) != 0)
                {
                    MonteurPartieImpl.joueurCourant.ville.Where(vi => vi.position.Item1 == t.Item1 & vi.position.Item2 == t.Item2).First();
                    afficherinfoVille(t, couleur);
                }
            }

            selectionRectangle.Visibility = System.Windows.Visibility.Visible;
            combatRectangle.Visibility = System.Windows.Visibility.Collapsed;
            buildCity.Visibility = System.Windows.Visibility.Collapsed;
            suggestion.Visibility = System.Windows.Visibility.Collapsed;
            finPartie();
        }

        /**
         * \fn afficherInfoUnite(Tuple<int, int> t, SolidColorBrush couleur)
         * \brief affiche les informations concernant les unites presentes dans la case
         * \param[in] t la position de la case
         */
        public void afficherInfoUnite(Tuple<int, int> t)
        {
            listUniteCase.Items.Clear();
            foreach (object o in carteGrid.Children)
            {
                if (o is Ellipse)
                {
                    Ellipse g = (Ellipse)o;
                    if (Grid.GetColumn(g) == t.Item1)
                    {
                        if (Grid.GetRow(g) == t.Item2)
                        {
                            if (g.Name.CompareTo("selectionUnite") != 0)
                            {
                                Unite u = g.Tag as Unite;
                                StackPanel stack = new StackPanel();
                                stack.Orientation = Orientation.Vertical;

                                Label label = new Label();

                                if (u is EtudiantEII)
                                {
                                    label.Content = "Etudiant EII";
                                }
                                else if (u is EnseignantEII)
                                {
                                    label.Content = "Enseignant EII";
                                }
                                else if (u is DirecteurEII)
                                {
                                    label.Content = "Directeur EII";
                                }
                                else if (u is EtudiantINFO)
                                {
                                    label.Content = "Etudiant INFO";
                                }
                                else if (u is EnseignantINFO)
                                {
                                    label.Content = "Enseignant INFO";
                                }
                                else if (u is DirecteurINFO)
                                {
                                    label.Content = "Directeur INFO";
                                }
                                stack.Children.Add(label);

                                Thickness thi = label.Margin;
                                thi.Left = 20;

                                label = new Label();
                                label.Margin = thi;
                                label.Content = "Vie : " + u.vie + "/" + u.vieMax;
                                stack.Children.Add(label);
                                label = new Label();
                                label.Margin = thi;
                                label.Content = "Attaque : " + u.attaque;
                                stack.Children.Add(label);
                                label = new Label();
                                label.Margin = thi;
                                label.Content = "Deplacement : " + (u.mouvement - u.deplacementEnCours);
                                stack.Children.Add(label);
                                label = new Label();
                                label.Margin = thi;
                                label.Content = "Defense : " + u.defense;
                                stack.Children.Add(label);

                                stack.Tag = g;
                                stack.MouseLeftButtonDown += new MouseButtonEventHandler(stack_MouseLeftButtonDown);
                                stack.KeyDown += this.Deplacement_KeyDown;

                                listUniteCase.Items.Add(stack);
                            }
                        }
                    }
                }
            }
        }

        /**
         * \fn afficherInfoVille(Tuple<int, int> t, SolidColorBrush couleur)
         * \brief affiche les informations concernant les villes presentes dans la case
         * \param[in] t la position de la case
         * \param[in] couleur du joueur courant
         */
        public void afficherinfoVille(Tuple<int,int> t, SolidColorBrush couleur)
        {
            Ville v = MonteurPartieImpl.joueurCourant.ville.Where(vi => vi.position.Item1 == t.Item1 & vi.position.Item2 == t.Item2).First();
            Label l1 = new Label();
            l1.Background = couleur;
            l1.Content = "Information sur la ville";
            Label info = new Label();
            info.Content = "Nombre d'habitants : " + v.nbHabitant
                         + "\nRessources en nourriture : " + v.ressourceNourr
                         + "\nRessources en minerai : " + v.ressourceMin;
            Label l2 = new Label();
            l2.Background = couleur;
            l2.Content = "Gestion de la ville";
            infoVille.Children.Add(l1);
            infoVille.Children.Add(info);
            infoVille.Children.Add(l2);

            if (v.prodEnCours)
            {
                Button b = new Button();
                b.Name = "stopProduction";
                b.Content = "Arrêter la production en cours";
                b.Click += new RoutedEventHandler(annulerProduction);
                infoVille.Children.Add(b);
            }
            else
            {
                Button b1 = new Button();
                Button b2 = new Button();
                Button b3 = new Button();

                b1.Name = "newDirecteur";
                b2.Name = "newTeacher";
                b3.Name = "newStudent";

                b1.Content = "Invoquer Directeur";
                b2.Content = "Invoquer nouvelle unité enseignante";
                b3.Content = "Invoquer nouvelle unité étudiante";

                b1.Click += new RoutedEventHandler(creerDirecteur);
                b2.Click += new RoutedEventHandler(creerEnseignant);
                b3.Click += new RoutedEventHandler(creerEtudiant);

                infoVille.Children.Add(b1);
                infoVille.Children.Add(b2);
                infoVille.Children.Add(b3);
            }
            villeCourante = v;
        }

        /**
         * \fn annulerProduction(object sender, RoutedEventArgs e)
         * \brief annule la production en cours
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        public void annulerProduction(object sender, RoutedEventArgs e)
        {
            villeCourante.annulerProduction();
            mettreAJour();
        }

        /**
         * \fn creerDirecteur(object sender, RoutedEventArgs e)
         * \brief creer un directeur si possible
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        public void creerDirecteur(object sender, RoutedEventArgs e)
        {
            Tuple<int, int> t = villeCourante.position;
            villeCourante.produireUniteDirecteur(t);
            mettreAJour();
        }

        /**
         * \fn creerEnseignant(object sender, RoutedEventArgs e)
         * \brief creer un enseignant si possible
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        public void creerEnseignant(object sender, RoutedEventArgs e)
        {
            Tuple<int, int> t = villeCourante.position;
            villeCourante.produireUniteEnseignant(t);
            mettreAJour();
        }

        /**
         * \fn creerEtudiant(object sender, RoutedEventArgs e)
         * \brief creer un etudiant si possible
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        public void creerEtudiant(object sender, RoutedEventArgs e)
        {
            Tuple<int, int> t = villeCourante.position;
            villeCourante.produireUniteEtudiant(t);
            mettreAJour();
        }

        /**
         * \fn rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
         * \brief gere l'evenement associe au clic gauche sur une case
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        void rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Grid rect = sender as Grid;
            infoVille.Children.Clear();
            Case caseClique = rect.Tag as Case;
            Grid.SetColumn(selectionRectangle, Grid.GetColumn(rect));
            Grid.SetRow(selectionRectangle, Grid.GetRow(rect));
           
            selectionRectangle.Tag = caseClique;

            mettreAJour();
            e.Handled = true;
        }

        /**
         * \fn Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
         * \brief gere l'evenement associe au clic gauche sur une ellipse
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        public void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Ellipse ell = sender as Ellipse;
            foreach (object o in carteGrid.Children)
            {
                if (o is Grid)
                {
                    Grid g = (Grid)o;
                    if (Grid.GetColumn(g) == Grid.GetColumn(ell))
                    {
                        if (Grid.GetRow(g) == Grid.GetRow(ell))
                        {
                            g.RaiseEvent(e);
                        }
                    }
                }
            }
        }

        /**
         * \fn rectangle_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
         * \brief gere l'evenement associe au clic droit sur une case
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        void rectangle_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            Ellipse ell = selectionUnite.Tag as Ellipse;
            if (ell != null)
            {
                Unite u = ell.Tag as Unite;

                if (u is UniteCombattante)
                {
                    Grid rect = sender as Grid;
                    Case caseClique = rect.Tag as Case;
                    int column = Grid.GetColumn(rect);
                    int row = Grid.GetRow(rect);

                    if (Grid.GetRow(selectionRectangle) <= row + 1 && Grid.GetRow(selectionRectangle) >= row - 1)
                    {
                        if (Grid.GetColumn(selectionRectangle) <= column + 1 && Grid.GetColumn(selectionRectangle) >= column - 1)
                        {
                            Grid.SetColumn(combatRectangle, column);
                            Grid.SetRow(combatRectangle, row);
                            combatRectangle.Tag = caseClique;
                            combatRectangle.Visibility = System.Windows.Visibility.Visible;
                        }
                    }
                }
            }

            e.Handled = true;
        }

        /**
         * \fn ville_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
         * \brief gere l'evenement associe au clic gauche sur une ville
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        void ville_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Grid grid = sender as Grid;

            foreach (object o in carteGrid.Children)
            {
                if (o is Grid)
                {
                    Grid g = (Grid)o;
                    if (Grid.GetColumn(g) == Grid.GetColumn(grid))
                    {
                        if (Grid.GetRow(g) == Grid.GetRow(grid))
                        {
                            g.RaiseEvent(e);
                        }
                    }
                }
            }
            var x = Grid.GetColumn(grid);
            var y = Grid.GetRow(grid);

            mettreAJour();
            e.Handled = true;
        }

        /**
         * \fn updateVille()
         * \brief met a jour l'affichage de la ville selectionnee
         */
        public void updateVille()
        {
            List<Ville> villesVisible = monteur.getJoueurCourant().getVilleVisible();

            foreach (object o in carteGrid.Children)
            {
                if (o is Grid)
                {
                    Grid g = o as Grid;
                    if (g.Tag is Joueur)
                    {
                        Joueur j = g.Tag as Joueur;
                        if (j != monteur.getJoueurCourant())
                        {
                            if (villesVisible.Where(v => v.position.Item1 == Grid.GetColumn(g) && v.position.Item2 == Grid.GetRow(g)).Count() == 0)
                            {
                                g.Visibility = System.Windows.Visibility.Hidden;
                            }
                            else
                            {
                                g.Visibility = System.Windows.Visibility.Visible;
                            }
                        }
                        else
                        {
                            g.Visibility = System.Windows.Visibility.Visible;
                        }
                    }
                }
            }
        }

        /**
         * \fn initVille()
         * \brief permet de creer les villes au chargement
         */
        public void initVille()
        {
            List<Ville> villesVisible = monteur.getJoueurCourant().getVilleVisible();

            foreach (object o in carteGrid.Children)
            {
                if (o is Grid)
                {
                    Grid g = o as Grid;
                    if (g.Tag is Joueur)
                    {
                        Joueur j = g.Tag as Joueur;
                        if (j != monteur.getJoueurCourant())
                        {
                            if (villesVisible.Where(v => v.position.Item1 == Grid.GetColumn(g) && v.position.Item2 == Grid.GetRow(g)).Count() == 0)
                            {
                                g.Visibility = System.Windows.Visibility.Hidden;
                            }
                        }
                    }
                }
            }
            if (monteur.getJoueurCourant().ville != null)
            {
                foreach (Ville v in monteur.getJoueurCourant().ville)
                {
                    Grid ville = new Grid();
                    Grid.SetColumn(ville, v.position.Item1);
                    Grid.SetRow(ville, v.position.Item2);
                    ImageBrush bi = new ImageBrush();
                    bi.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.chateau.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                    ville.Background = bi;
                    ville.Tag = monteur.getJoueurCourant();
                    carteGrid.Children.Add(ville);
                    ville.MouseLeftButtonDown += new MouseButtonEventHandler(ville_MouseLeftButtonDown);
                }
            }
        }

        /**
         * \fn updateUnit()
         * \brief met a jour l'ensemble des unites de la carte
         */
        public void updateUnit()
        {
            List<Ellipse> toBeRemove = new List<Ellipse>();

            foreach (object o in carteGrid.Children)
            {
                if (o is Ellipse)
                {
                    Ellipse ell1 = o as Ellipse;
                    if (ell1.Name.CompareTo("selectionUnite") != 0)
                    {
                        toBeRemove.Add(ell1);
                    }
                }
            }

            foreach (Ellipse ellipse in toBeRemove)
            {
                carteGrid.Children.Remove(ellipse);
            }

            //foreach (Joueur j in MonteurPartieImpl.joueur)
            //{
                foreach (Unite u in monteur.getJoueurCourant().Unite)
                {
                    Ellipse ell = new Ellipse();

                    ell.Height = 20;
                    ell.Width = 20;
                    ell.Tag = u;
                    ell.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;

                    if (u is Etudiant)
                    {
                        ell.Fill = Brushes.Blue;
                    }
                    else if (u is Enseignant)
                    {
                        ell.Fill = Brushes.Red;
                    }
                    else if (u is Directeur)
                    {
                        ell.Fill = Brushes.Green;
                    }

                    Grid.SetColumn(ell, u.position.Item1);
                    Grid.SetRow(ell, u.position.Item2);

                    carteGrid.Children.Add(ell);
                }

                foreach (Unite u in monteur.getJoueurCourant().getUniteVisible())
                {
                    Ellipse ell = new Ellipse();

                    ell.Height = 20;
                    ell.Width = 20;
                    ell.Tag = u;
                    ell.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;

                    if (u is Etudiant)
                    {
                        ell.Fill = Brushes.Blue;
                    }
                    else if (u is Enseignant)
                    {
                        ell.Fill = Brushes.Red;
                    }
                    else if (u is Directeur)
                    {
                        ell.Fill = Brushes.Green;
                    }

                    Grid.SetColumn(ell, u.position.Item1);
                    Grid.SetRow(ell, u.position.Item2);

                    carteGrid.Children.Add(ell);
                }
            //}
        }

        /**
         * \fn stack_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
         * \brief gere l'evenement associe au clic gauche sur la liste des unites
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        void stack_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            StackPanel stack = sender as StackPanel;

            Ellipse ell = stack.Tag as Ellipse;
            Unite u = ell.Tag as Unite;

            selectionUnite.Tag = ell;
            int column = u.position.Item1;
            int row = u.position.Item2;

            Grid.SetColumn(selectionUnite, column);
            Grid.SetRow(selectionUnite, row);
            selectionUnite.Visibility = System.Windows.Visibility.Visible;

            if (u is UniteColon && u.joueur==monteur.getJoueurCourant())
            {
                suggestion.Visibility = System.Windows.Visibility.Visible;
                buildCity.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                suggestion.Visibility = System.Windows.Visibility.Collapsed;
                buildCity.Visibility = System.Windows.Visibility.Collapsed;
            }
        }

        /**
         * \fn tourSuivant(object sender, MouseButtonEventArgs e)
         * \brief passe au tour suivant
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        public void tourSuivant(object sender, RoutedEventArgs e)
        {
            villeConstruite = false;
            MonteurPartieImpl.joueurCourant.setLastPos(new Tuple<int,int>(Grid.GetColumn(selectionRectangle),Grid.GetRow(selectionRectangle)));
            monteur.tourSuivant();

            if (villeCourante != null)
            {
                villeCourante.produire();
            }
            joueurCourant.Tag = monteur.getJoueurCourant();
            Tuple<int, int> t = new Tuple<int,int>(0,0);
            if (MonteurPartieImpl.joueurCourant.getLastPos() != null)
            {
                t = MonteurPartieImpl.joueurCourant.getLastPos();
            }
            else
            {
                t = MonteurPartieImpl.joueurCourant.Unite.First().position;
            }
            Grid.SetColumn(selectionRectangle, t.Item1);
            Grid.SetRow(selectionRectangle, t.Item2);
            scrollCarte.ScrollToVerticalOffset((t.Item2 - 7) * 30);
            scrollCarte.ScrollToHorizontalOffset((t.Item1 - 7) * 30);

            mettreAJour();
            updateUnit();
            updateVille();

            suggestion1.Visibility = System.Windows.Visibility.Collapsed;
            suggestion2.Visibility = System.Windows.Visibility.Collapsed;
            suggestion3.Visibility = System.Windows.Visibility.Collapsed;
        }

        /**
         * \fn finPartie()
         * \brief se lance quand la partie est finie
         */
        public void finPartie(){
            Joueur j = monteur.joueurGagnant();
            if(j!=null){
                MessageBox.Show("Le joueur "+j.NomJoueur+" a gagné !");
                _main.content.Content = new ChoixCarte(_main);
            }

        }

        /**
         * \fn construireVille(object sender, MouseButtonEventArgs e)
         * \brief construit la ville
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        public void construireVille(object sender, RoutedEventArgs e)
        {
            if (villeConstruite)
            {
                MessageBox.Show("Une Ville a déjà été construite ce tour-ci");
            }
            else
            {
                var x = Grid.GetColumn(selectionRectangle);
                var y = Grid.GetRow(selectionRectangle);

                var pos = new Tuple<int, int>(x, y);

                Joueur j = monteur.getJoueurCourant();
                IEnumerable<Unite> listEnseignant = j.Unite.Where(l => l is Enseignant);
                foreach (Enseignant u in listEnseignant)
                {
                    var posUnite = u.position;
                    var pos1 = posUnite.Item1;
                    var pos2 = posUnite.Item2;
                    if (pos1 == x & pos2 == y)
                    {
                        u.batirVille(taille);
                        Grid ville = new Grid();
                        Grid.SetColumn(ville, x);
                        Grid.SetRow(ville, y);
                        ImageBrush bi = new ImageBrush();
                        bi.ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(CivilisationWPF.Properties.Resources.chateau.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                        ville.Background = bi;
                        carteGrid.Children.Add(ville);
                        ville.MouseLeftButtonDown += new MouseButtonEventHandler(ville_MouseLeftButtonDown);
                        villeConstruite = true;
                        ville.Tag = monteur.getJoueurCourant();
                        break;
                    }
                }
            }
            if (villeConstruite == false)
            {
                MessageBox.Show("Aucune unité Enseignante ne se trouve sur la case sélectionnée");
            }
            updateUnit();
            mettreAJour();

            suggestion1.Visibility = System.Windows.Visibility.Collapsed;
            suggestion2.Visibility = System.Windows.Visibility.Collapsed;
            suggestion3.Visibility = System.Windows.Visibility.Collapsed;
        }

        /**
         * \fn suggestionPosition(object sender, MouseButtonEventArgs e)
         * \brief affiche les suggestions de placement des villes
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        public void suggestionPosition(object sender, RoutedEventArgs e)
        {
            List<Tuple<int,int>> sug = monteur.suggestions();
            for (int i = 1 ; i <= 3 ; i++){
                Tuple<int, int> t = sug.First();
                sug.Remove(sug.First());
                foreach (object o in carteGrid.Children)
                {
                    if (o is Rectangle)
                    {
                        Rectangle r = (Rectangle)o;
                        if (r.Name.CompareTo("suggestion" + i) == 0)
                        {
                            Grid.SetColumn(r, t.Item1);
                            Grid.SetRow(r, t.Item2);
                            r.Visibility = System.Windows.Visibility.Visible;
                        }
                    }
                }
            }
        }

        /**
         * \fn Deplacement_KeyDown(object sender, MouseButtonEventArgs e)
         * \brief gere le deplacement des unites
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        private void Deplacement_KeyDown(object sender, KeyEventArgs e)
        {
            if (selectionUnite.IsVisible)
            {
                Ellipse ell = selectionUnite.Tag as Ellipse;
                Unite u = ell.Tag as Unite;
                if (e.Key == Key.Enter)
                {
                    this.tourSuivant(sender,e);
                }
                if (u.joueur == monteur.getJoueurCourant())
                {
                    if (u.peutDeplacer())
                    {
                        if (e.Key == Key.Up)
                        {
                            u.deplacer(Direction.Haut);
                            Grid.SetRow(ell, u.position.Item2);
                            Grid.SetRow(selectionRectangle, u.position.Item2);
                        }
                        else if (e.Key == Key.Down)
                        {
                            u.deplacer(Direction.Bas);
                            Grid.SetRow(ell, u.position.Item2);
                            Grid.SetRow(selectionRectangle, u.position.Item2);
                        }
                        else if (e.Key == Key.Left)
                        {
                            u.deplacer(Direction.Gauche);
                            Grid.SetColumn(ell, u.position.Item1);
                            Grid.SetColumn(selectionRectangle, u.position.Item1);
                        }
                        else if (e.Key == Key.Right)
                        {
                            u.deplacer(Direction.Droite);
                            Grid.SetColumn(ell, u.position.Item1);
                            Grid.SetColumn(selectionRectangle, u.position.Item1);
                        }

                        foreach (Joueur j in MonteurPartieImpl.joueur.Where(jo => jo != MonteurPartieImpl.joueurCourant))
                        {
                            if (j.ville != null)
                            {
                                foreach (Ville v in j.ville)
                                {
                                    if (u.position.Item1 == v.position.Item1 & u.position.Item2 == v.position.Item2)
                                    {
                                        MessageBox.Show("Ville conquise !");
                                        v.changerCivilisation(MonteurPartieImpl.joueurCourant);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                updateUnit();
                updateVille();
                mettreAJour();

                e.Handled = true;
            }
        }

        /**
         * \fn engagerCombatClick(object sender, MouseButtonEventArgs e)
         * \brief gere le combat entre les unites
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        public void engagerCombatClick(object sender, RoutedEventArgs e)
        {
            if (selectionUnite.IsVisible)
            {
                Ellipse ell = selectionUnite.Tag as Ellipse;
                Unite u = ell.Tag as Unite;
                if (u is UniteCombattante)
                {
                    Etudiant etu = u as Etudiant;

                    int column = Grid.GetColumn(combatRectangle);
                    int row = Grid.GetRow(combatRectangle);

                    int res = etu.engagerCombat(new Tuple<int, int>(column, row));

                    if(res==1) {
                        Grid.SetColumn(ell,column);
                        Grid.SetRow(ell,row);

                        this.updateUnit();
                    }
                    else if (res == 0)
                    {
                        carteGrid.Children.Remove(ell);
                    }
                }
            }
            mettreAJour();
        }

        /**
         * \fn sauverJeu(object sender, MouseButtonEventArgs e)
         * \brief sauvegarde la partie
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        public void sauverJeu(object sender, RoutedEventArgs e)
        {
            new SavePartie(monteur).Show();
        }

        /**
         * \fn quitterPartie(object sender, MouseButtonEventArgs e)
         * \brief quitte la partie
         * \param[in] sender l'objet qui fait appel a la methode
         * \param[in] e l'evenement lance
         */
        public void quitterPartie(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("Voulez-vous quitter la partie ?", "Quitter la partie", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                _main.content.Content = new ChoixCarte(_main);
            }
        }
    }
}